using System;
using System.Collections;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.FormsManagement;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.ScriptEngine;
using PHSRAG.Utility;
using PHSRAG.WebControls;
using ScriptReference = PHSRAG.Insight21.ScriptEngine.ScriptReference;

namespace PHSRAG.Insight21.COI
{
    /// <summary>
    /// Allows the user select Outside Entities or add new ones.
    /// </summary>
    public partial class OutsideEntitySelectionPage : BasePage
    {
        #region Private Member Variables

        private int _admPersonId;
        private ICachePolicy _cachePolicy;
        private ConflictOfInterest _coi;
        private int _coiId;
        private bool _fromForm;
        private ICachePolicy _pageCachePolicy;
        private int _questionnaireAnswerId;
        private int _questionnaireVersionId;
        private bool _showAsPopUp;
        private bool _uiForOutsideEntity = true;

        #endregion

        #region Private properties

        /// <summary>
        /// Gets the COI object.
        /// If it's not already in the cache, it loads it up based on the coiId passed to the page, and caches the object
        /// </summary>
        private ConflictOfInterest CurrentConflictOfInterest
        {
            get
            {
                if ((_coi == null) || (_coiId != _coi.Id))
                {
                    _coi = new ConflictOfInterest(_cachePolicy);
                    _coi.Load(DataAccess.GetConnectionString(), _coiId);
                }
                return _coi;
            }
        }

        #endregion

        #region Page Event Handlers

        /// <summary>
        /// Looks for a cached person id and name. If found, displays the name in the breadcrumb.
        /// 
        /// Retrives the coi id and the questionnaire version id from the cache
        /// </summary>
        /// <param name="sender">Object that raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                annunciator.Message = string.Empty;
                annunciator.MessageType = Annunciator.MessageTypes.Error;
                if (Request.QueryString["fromform"] != null)
                {
                    _fromForm = Convert.ToBoolean(Request.QueryString["fromform"]);
                }
                if (_fromForm)
                {
                    cancel.Visible = false;
                    _showAsPopUp = true;
                }
                else
                {
                    cancel.Visible = true;
                }

                if (Request.QueryString["uiforoutsideentitykey"] != null)
                {
                    _uiForOutsideEntity = Convert.ToBoolean(Request.QueryString["uiforoutsideentitykey"]);
                }

                string name = string.Empty;
                _admPersonId = ((UserContext) _cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId;

                Hashtable incomingData = _pageCachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
                if (incomingData != null)
                {
                    if (incomingData.ContainsKey(Keys.FullNameKey))
                    {
                        name = Convert.ToString(incomingData[Keys.FullNameKey]);
                    }
                    if (incomingData.ContainsKey(Keys.AdmPersonIdKey))
                    {
                        _admPersonId = Convert.ToInt32(incomingData[Keys.AdmPersonIdKey]);
                    }
                    if (incomingData.ContainsKey(Keys.ShowAsPopUp))
                    {
                        _showAsPopUp = _showAsPopUp || Convert.ToBoolean(incomingData[Keys.ShowAsPopUp]);
                    }
                    if (incomingData.ContainsKey(Keys.UIForOutsideEntityKey))
                    {
                        _uiForOutsideEntity = _uiForOutsideEntity || Convert.ToBoolean(incomingData[Keys.UIForOutsideEntityKey]);
                    }

                    if (!_uiForOutsideEntity)
                    {
                        outsideEntitySearchLabel.Visible = false;
                        outsideEntitySearchResultsLabel.Visible = false;
                        outsideEntityAddNewLabel.Visible = false;
                        employerSearchLabel.Visible = true;
                        employerSearchResultsLabel.Visible = true;
                        employerAddNewLabel.Visible = true;
                    }
                    _questionnaireVersionId = Convert.ToInt32(incomingData[Keys.QuestionnaireVersionIdKey]);
                    _questionnaireAnswerId = Convert.ToInt32(incomingData[Keys.QuesionnaireAnswerIdKey]);
                    _coiId = Convert.ToInt32(incomingData[Keys.COIIdKey]);
                }
                else
                {
                    throw new Exception("Page is being viewed out of context");
                }

                breadCrumb.Add(((name.Length > 0) ? string.Format("Entity Selection - {0}", name) : "Entity Selection"),
                    Settings.GetKeyValue("SubNavigation.CoI.EntitySelectionPageURL", ""),
                    Settings.GetKeyValue("BreadCrumb.DetailPageLevel", 2));

                //if page is being shown as popup, then hide the header section
                headerSection.Visible = !_showAsPopUp;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region Web Form Designer generated code

        /// <summary>
        /// Page Initialization
        /// </summary>
        /// <param name="e">Arguments associated with the event</param>
        protected override void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            base.OnInit(e);
            _cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            _pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
        }

        #endregion

        #region Control Event Handlers

        /// <summary>
        /// Displays the selected item in the search text box
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnEntityListSelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (entityList.SelectedIndex >= 0)
                {
                    entityName.Text = entityList.SelectedItem.Text;
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Resets the subnavigation selected link before the header or the breadCrumb performs a redirect.
        /// Uncache all the cached details
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                coiSubNavigation.Reset();
                coiSubModNavigation.Reset();
                RemoveOutSideEntityKeys();
                UncacheInterModuleNavigationDetails();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Resets the subnavigation selected link before the breadCrumb performs a redirect.
        /// Uncache COI.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnBreadCrumbNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                coiSubModNavigation.Reset();
                UncacheCOIDetails();
                UncacheUserDetails();
                RemoveOutSideEntityKeys();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Uncache details specific to the page
        /// </summary>
        /// <param name="sender">Object that raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnCOISubModNavigationNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                UncacheIntraModuleNavigationDetails();
                RemoveOutSideEntityKeys();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Redirects the user to the COIOverview page after uncaching the page specific details
        /// </summary>
        /// <param name="sender">Object that raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnCancel(object sender, ImageClickEventArgs e)
        {
            try
            {
                UncacheIntraModuleNavigationDetails();
                RemoveOutSideEntityKeys();
                Response.Redirect(Settings.GetKeyValue("SubNavigation.CoI.COIOverviewURL", ""), false);
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// If Add Entity checkbox is checked, then adds the new entity to database.
        /// 
        /// Constructs a QuestionnaireAnswer object, sets the properties and saves it to the database
        /// 
        /// Inserts the questionnaireanswer id in the cache and redirects to the Questionnaire Answer page
        /// </summary>
        /// <param name="sender">Object that raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnSave(object sender, ImageClickEventArgs e)
        {
            try
            {
                if (addEntity.Checked && newEntityName.Text.Trim() == string.Empty)
                {
                    annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                    annunciator.Message = "Name of the new Entity cannot be blank";
                    return;
                }
                if (!addEntity.Checked && (entityList.Items.Count == 0 || entityList.SelectedIndex < 0))
                {
                    annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                    annunciator.Message = "No Entity is selected.";
                    return;
                }

                if (_fromForm)
                {
                    COIOrganization newOrg;
                    string orgName;
                    int orgValue;
                    if (addEntity.Checked)
                    {
                        newOrg = new COIOrganization(_cachePolicy);
                        newOrg.Name = newEntityName.Text.Trim();
                        newOrg.AdmPersonId = _admPersonId;
                        newOrg.Save(DataAccess.ConnectionString);
                        orgName = newOrg.Name;
                        orgValue = newOrg.Id;
                    }
                    else
                    {
                        orgName = entityList.SelectedItem.Text;
                        orgValue = int.Parse(entityList.SelectedValue);
                    }

                    Page.ClientScript.RegisterStartupScript(GetType(), "UpdateParent", string.Format(
                        "<script language=\"javascript\">UpdateParent('{0}|{1}');</script>", orgValue, orgName.Replace("'", @"\'")));
                    return;
                }


                QuestionnaireAnswer questAnswer = new QuestionnaireAnswer(_cachePolicy);

                if (_questionnaireAnswerId == 0)
                {
                    questAnswer.QuestionnaireVersionId = _questionnaireVersionId;
                    questAnswer.QuestionnaireCategory = questAnswer.QuestionnaireVersion.Questionnaire.Category;
                }
                else
                {
                    questAnswer.Load(DataAccess.ConnectionString, _questionnaireAnswerId);
                }

                Script answerFillerScript =
                    (Script) questAnswer.QuestionnaireVersion.Scripts[FormsManagement.Constants.ScriptType.AnswerFiller];

                if (answerFillerScript != null)
                {
                    using (ScriptEngineHost scriptHost =
                        new ScriptEngineHost(
                            string.Format("{0}{1}", _questionnaireVersionId,
                                ScriptEngine.Constants.RootMoniker.AnswerFillerScriptMoniker),
                            ScriptEngine.Constants.RootNamespaces.AnswerFillerScript,
                            true))
                    {
                        ArrayList refs = ScriptReference.GetAllScriptReferences(
                            DataAccess.GetConnectionString());

                        for (int i = 0; i < refs.Count; ++i)
                        {
                            ScriptReference reference = (ScriptReference) refs[i];
                            scriptHost.AddDLLReference(reference.Path);
                        }


                        // add the connection string
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ConnectionString,
                            DataAccess.GetConnectionString());
                        // add the caching policy
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.CachePolicy, _cachePolicy);
                        // add this COI as an intrinsic.
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.COI, CurrentConflictOfInterest);
                        // add the QuestionnaireAnswer
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.QuestionnaireAnswer,
                            questAnswer);
                        // add the params
                        COIParams coiParams = new COIParams();
                        coiParams.IsNewOutsideEntity = addEntity.Checked;
                        coiParams.AdmPersonId = _admPersonId;
                        coiParams.OutsideEntityName = (addEntity.Checked) ? newEntityName.Text.Trim() : entityList.SelectedItem.Text;
                        coiParams.OutsideEntitySelectedValue = (addEntity.Checked) ? 0 : int.Parse(entityList.SelectedValue);
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.COIParams,
                            coiParams);

                        // compile and run the script.
                        if (scriptHost.Compile(answerFillerScript))
                        {
                            scriptHost.RunScript(answerFillerScript,
                                ScriptEngine.Constants.AssemblyType.AnswerFillerScript,
                                ScriptEngine.Constants.MethodsToRun.Main);
                        }
                    }
                }

                CurrentConflictOfInterest.QuestionnaireAnswers = null;
                Hashtable incomingData = _pageCachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
                incomingData[Keys.QuesionnaireAnswerIdKey] = questAnswer.Id;
                RemoveOutSideEntityKeys();
                Response.Redirect(Settings.GetKeyValue("SubNavigation.CoI.AnswerChartURL", ""), false);
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Searches the database for entities with the name specified and binds it to the dropdown
        /// </summary>
        /// <param name="sender">Object that raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnSearchEntity(object sender, ImageClickEventArgs e)
        {
            try
            {
                addEntity.Enabled = true;
                entityList.DataSource = COIOrganizationCollection.GetOrganizations(entityName.Text.Trim());
                entityList.DataTextField = "Name";
                entityList.DataValueField = "Id";
                entityList.DataBind();

                if (entityList.Items.Count > 0)
                {
                    searchResultsPanel.Visible = true;
                }
                else
                {
                    annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                    annunciator.Message = "No results are found.  Please search again or click the \"Add New\" check box to enter an entity, then click \"Continue\".";
                    searchResultsPanel.Visible = false;
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Toggles visibility of controls based on the status of the checkbox
        /// </summary>
        /// <param name="sender">Object that raised the event</param>
        /// <param name="e">Arguments associated with the event</param>
        protected void OnAddEntityCheckedChanged(object sender, EventArgs e)
        {
            try
            {
                if (addEntity.Checked)
                {
                    newEntityName.Enabled = true;
                    newEntityName.Text = entityName.Text;
                    entityList.Items.Clear();
                    searchResultsPanel.Visible = false;
                    entityName.Text = string.Empty;
                    entityName.Enabled = false;
                    searchEntity.Visible = false;
                }
                else
                {
                    searchResultsPanel.Enabled = true;
                    newEntityName.Text = string.Empty;
                    newEntityName.Enabled = false;
                    entityName.Enabled = true;
                    searchEntity.Visible = true;
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Displays an error message on the screen to the user with the exception, and all
        /// inner exception messages.
        /// </summary>
        /// <param name="ex">The exception to report on</param>
        private void DisplayExceptionReport(Exception ex)
        {
            annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
            annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
        }


        /// <summary>
        /// Removes all the details that are specific to the COI Module from cache
        /// </summary>
        private void UncacheInterModuleNavigationDetails()
        {
            Hashtable incomingData = _pageCachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
            if (incomingData != null)
            {
                UncacheUserDetails();
                if (incomingData.ContainsKey(Keys.ShowAsPopUp))
                {
                    incomingData.Remove(Keys.ShowAsPopUp);
                }

                incomingData.Remove(Keys.QuestionnaireVersionIdKey);
            }
            UncacheCOIDetails();
        }


        /// <summary>
        /// Remove the fwkdomainuserid and the username, if exists, from the cache
        /// </summary>
        private void UncacheUserDetails()
        {
            Hashtable incomingData = _pageCachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
            if (incomingData != null)
            {
                if (incomingData.ContainsKey(Keys.FullNameKey))
                {
                    incomingData.Remove(Keys.FullNameKey);
                }
                if (incomingData.ContainsKey(Keys.AdmPersonIdKey))
                {
                    incomingData.Remove(Keys.AdmPersonIdKey);
                }
            }
        }


        /// <summary>
        /// Uncache COI
        /// </summary>
        private void UncacheCOIDetails()
        {
            Hashtable incomingData = _pageCachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
            if (incomingData != null)
            {
                incomingData.Remove(Keys.COIIdKey);
            }
            _coi = _cachePolicy.GetCachedObject(ConflictOfInterest.COIKey) as ConflictOfInterest;
            if (_coi != null)
            {
                _coi.UnCache();
            }
        }


        /// <summary>
        /// Removes all the details specific to the page from cache
        /// </summary>
        private void UncacheIntraModuleNavigationDetails()
        {
            Hashtable incomingData = _pageCachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
            if (incomingData != null)
            {
                incomingData.Remove(Keys.QuestionnaireVersionIdKey);
            }
            if (_coi != null)
            {
                _coi.QuestionnaireAnswers = null;
            }
        }

        /// <summary>
        /// Removes outside entity key
        /// </summary>
        private void RemoveOutSideEntityKeys()
        {
            Hashtable incomingData = _pageCachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
            if (incomingData.ContainsKey(Keys.UIForOutsideEntityKey))
            {
                incomingData.Remove(Keys.UIForOutsideEntityKey);
            }
            if (incomingData.ContainsKey(Keys.CurrentEmployerKey))
            {
                incomingData.Remove(Keys.CurrentEmployerKey);
            }
        }

        #endregion
    }
}